home *** CD-ROM | disk | FTP | other *** search
/ Aminet 19 / Aminet 19 (1997)(GTI - Schatztruhe)[!][Jun 1997].iso / Aminet / util / blank / GBLvshuf.lha / LivingShuffle / Dev / blank.c next >
C/C++ Source or Header  |  1997-04-07  |  31KB  |  729 lines

  1. /*
  2.  *  Copyright (c) 1997 Ingo Schmiegel
  3.  *  All rights reserved.
  4.  *
  5.  */
  6.  
  7. #include <exec/memory.h>
  8. #include "/includes.h"
  9. #include <clib/intuition_protos.h>
  10. #include <intuition/intuitionbase.h>
  11. #include <math.h>
  12. #include <time.h>
  13.  
  14. #define PREFS_UPDATE  0                 /* update the pieces or simple shuffle */
  15. #define PREFS_HORIZ   2                 /* number of columns in the puzzle */
  16. #define PREFS_VERT    4                 /* number of rows in the puzzle */
  17. #define PREFS_DIVIS   6                 /* number of steps for one shuffle movement */
  18. #define PREFS_HOLE    8                 /* hole filling mode */
  19. #define PREFS_BORDER  10                /* draw border around the pieces? */
  20. #define PREFS_DELAY   12                /* delay between two such steps */
  21. #define PREFS_SCREEN  14                /* select from which screen cloning should take place */
  22. #define PREFS_FADEPCT 16                /* percent of brightness of the original colours */
  23.  
  24. #define PREFS_UPDATE_YES        0
  25. #define PREFS_UPDATE_NO         1
  26. #define PREFS_HOLE_BACKGROUND   0
  27. #define PREFS_HOLE_ONCERANDOM   1
  28. #define PREFS_HOLE_RANDOM       2
  29. #define PREFS_BORDER_YES        0
  30. #define PREFS_BORDER_NO         1
  31. #define PREFS_SCREEN_FRONT      0
  32. #define PREFS_SCREEN_PUBLIC     1
  33.  
  34. #include "LivingShuffle_rev.h"
  35. STATIC const UBYTE VersTag[] = VERSTAG;
  36.  
  37. /* maximum puzzle pieces */
  38. #define     PUZZLE_MAX_ROWS     50
  39. #define     PUZZLE_MAX_COLUMNS  50
  40. /* minimum piece size (rows and columns values will be adjusted) (MUST BE AT LEAST 4!!) */
  41. #define     PIECE_MIN_WIDTH     8
  42. #define     PIECE_MIN_HEIGHT    8
  43.  
  44. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  45.  *  Piece           - describing one piece of the puzzle
  46.  *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  47. typedef struct _Piece
  48. {
  49.     long    srcx;     /* source topleft coordinate (in columns and rows) */
  50.     long    srcy;     /* the destination coordinate is its position in the puzzle array */
  51. } Piece;
  52.  
  53. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  54.  *  Puzzle           - describing the puzzle
  55.  *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  56. enum   _direction   { up, down, left, right };
  57. typedef enum _direction     direction;
  58.  
  59. typedef struct _Puzzle
  60. {
  61.     long    columns;  /* Size (columns,rows) */
  62.     long    rows;
  63.     long    steps;    /* steps to do during one piece movement */
  64.     long    pw;       /* Size of one piece in pixels */
  65.     long    ph;
  66.  
  67.     struct Screen *srcscr;   /* source screen (only screen pointer here for SAFETY!) */
  68.     struct RastPort *destrp;  /* destination screen's rastport */
  69.  
  70.     Piece   pieces[PUZZLE_MAX_ROWS][PUZZLE_MAX_COLUMNS]; /* Array of pieces */
  71.  
  72.     BOOL    doborder;
  73.  
  74.                 /* these values are updated before a new shuffle is started */
  75.     long    hx;     /* hole position    */
  76.     long    hy;
  77.     long    step;   /* actual step */
  78.     long    from;   /* direction of actual movement (fill hole with piece from <from> direction) */
  79. } Puzzle;
  80.  
  81. /************************************************************************************************/
  82. /************************************************************************************************/
  83. /************************************************************************************************/
  84.  
  85. Puzzle  puzzle;
  86.  
  87. const long  ColBack = 0;        /* Background colour */
  88. const long  ColDarkEdge = 1;    /* Colour of the bottom right dark edges */
  89. const long  ColBrightEdge = 2;  /* Colour of the top left bright edges */
  90.       long  ColHole;            /* Is once (or more often) randomly selected by main() */
  91. /************************************************************************************************/
  92. /************************************************************************************************/
  93. /************************************************************************************************/
  94.  
  95. void Defaults(PrefObject *Prefs)
  96. {
  97.     Prefs[PREFS_UPDATE].po_Level = PREFS_UPDATE_YES;
  98.     Prefs[PREFS_HORIZ].po_Level = 10;
  99.     Prefs[PREFS_VERT].po_Level = 8;
  100.     Prefs[PREFS_DIVIS].po_Level = 10;
  101.     Prefs[PREFS_HOLE].po_Active = PREFS_HOLE_BACKGROUND;
  102.     Prefs[PREFS_BORDER].po_Active = PREFS_BORDER_YES;
  103.     Prefs[PREFS_DELAY].po_Level = 1;
  104.     Prefs[PREFS_SCREEN].po_Active = PREFS_SCREEN_FRONT;
  105.     Prefs[PREFS_FADEPCT].po_Level = 25;
  106. }
  107.  
  108. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  109.  * OpenLibs          "Open all needed libraries"
  110.  *
  111.  * Result:      TRUE or FALSE
  112.  *
  113.  * Function:    Opens the needed libraries
  114.  *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  115. BOOL OpenLibs(void)
  116. {
  117.     return TRUE;
  118. }
  119. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  120.  * CloseLibs          "Close all needed libraries"
  121.  *
  122.  * Function:    Closes all opened libraries
  123.  *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  124. void CloseLibs(void)
  125. {
  126. }
  127. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  128. * RndBT                (macro)         "Random from Bottom to Top"
  129. *
  130. * Parameters:  min     The minimum of possible random numbers (any of: int,char,word,long; no floats!)
  131. *              max     The maximum of possible random numbers (dito)
  132. *              (Do not use negative numbers!)
  133. *
  134. * Result:      long    A random number
  135. *
  136. * Function:    Returns a random number in the interval of [min..max] (both included)
  137. *
  138. * Note:        Call srand48() once before using this function to set a seek value,
  139. *              e.g.: srand48(time(NULL))
  140. *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  141. #define RndBT(min,max)  ((min)+(lrand48()%((max)-(min)+1)))
  142.  
  143.  
  144. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  145.  * DrawRectBorder           "Draw the border of one rectangle"
  146.  *
  147.  * Parameters:  left edge, top edge, right edge, bottom edge
  148.  *
  149.  * Result:      none
  150.  *
  151.  * Function:    Draws a frame around a rectangle, light shines from the top left
  152.  *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  153. void DrawRectBorder (long xl, long yt, long xr, long yb)
  154. {
  155.     SetAPen(puzzle.destrp,ColDarkEdge);
  156.     Move(puzzle.destrp,xr,yt);
  157.     Draw(puzzle.destrp,xr,yb);
  158.     Draw(puzzle.destrp,xl,yb);
  159.     SetAPen(puzzle.destrp,ColBrightEdge);
  160.     Draw(puzzle.destrp,xl,yt);
  161.     Draw(puzzle.destrp,xr,yt);
  162. }
  163. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  164.  * getNewDir           "Get a new direction"
  165.  *
  166.  * Parameters:  none
  167.  *
  168.  * Result:      none
  169.  *
  170.  * Function:    sets the direction field in the puzzle, so that the next shuffle movement
  171.  *              can be done.
  172.  *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  173. void getNewDir(void)
  174. {            /*  pos of hole ,    grid dimensions  , last movemetn direction */
  175.     direction dir;
  176.     for(;;)
  177.     {
  178.         dir=(direction)RndBT(0,3);
  179.         switch (dir)
  180.         {
  181.             case left:  if (puzzle.hx == 0)       break;              /* try again */
  182.                         if (puzzle.from == right) break;              /* try again */
  183.                         puzzle.from = dir;        return;
  184.             case right: if (puzzle.hx == (puzzle.columns-1)) break;   /* try again */
  185.                         if (puzzle.from == left)             break;   /* try again */
  186.                         puzzle.from = dir;                   return;
  187.             case up:    if (puzzle.hy == 0)      break;               /* try again */
  188.                         if (puzzle.from == down) break;               /* try again */
  189.                         puzzle.from = dir;       return;
  190.             case down:  if (puzzle.hy == (puzzle.rows-1)) break;      /* try again */
  191.                         if (puzzle.from == up)            break;      /* try again */
  192.                         puzzle.from = dir;                return;
  193.         }
  194.     }
  195. }
  196. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  197.  * initPuzzle        "Initialize the puzzle"
  198.  *
  199.  * Parameters:
  200.  *
  201.  * Result:      none
  202.  *
  203.  * Function:    Initializes all fields
  204.  *
  205.  * Note:    Ever call this function with valid screen pointers !!!
  206.  *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  207. void initPuzzle (struct Screen *src, struct Screen *dest, long columns, long rows, long steps)
  208. {
  209.     long    r,c;
  210.  
  211.     puzzle.columns = columns;
  212.     puzzle.rows = rows;
  213.     puzzle.steps = steps;
  214.     puzzle.pw = dest->Width / columns;
  215.     puzzle.ph = dest->Height / rows;
  216.  
  217.     puzzle.srcscr = src;
  218.     puzzle.destrp = &(dest->RastPort);
  219.  
  220.     puzzle.hx = RndBT(0,columns-1);
  221.     puzzle.hy = RndBT(0,rows-1);
  222.     puzzle.step = 0;
  223.     puzzle.from = (direction)RndBT(0,3);
  224.     getNewDir();  /* to do bordercorrections */
  225.  
  226.     /* Initialize the pieces */
  227.     for (r=0;r<rows;r++)
  228.     {
  229.         for (c=0;c<columns;c++)
  230.         {
  231.             puzzle.pieces[r][c].srcx = c;
  232.             puzzle.pieces[r][c].srcy = r;
  233.             if (puzzle.doborder)
  234.                 DrawRectBorder( c*puzzle.pw, r*puzzle.ph, (c+1)*puzzle.pw-1, (r+1)*puzzle.ph-1 );
  235.         }
  236.     }
  237.     if (puzzle.doborder)
  238.     {
  239.         /* Now draw a nice right border puzzle (which isn't shuffled, because it's too small) */
  240.         if ((columns*puzzle.pw) < (dest->Width-2))
  241.         {   /* enough room for a nice right border */
  242.             for (r=0;r<rows;r++)
  243.                 DrawRectBorder(columns*puzzle.pw, r*puzzle.ph,
  244.                                dest->Width-1,     (r+1)*puzzle.ph-1);
  245.         }
  246.         else if ((columns*puzzle.pw) < dest->Width)
  247.         {   /* not enough room for a nice right border but a background strip */
  248.             SetAPen(puzzle.destrp,ColBack);
  249.             RectFill(puzzle.destrp,
  250.                      columns*puzzle.pw, 0,
  251.                      dest->Width-1,     dest->Height-1);
  252.         }
  253.         /* Now draw a nice bottom border puzzle (which isn't shuffled, because it's too small) */
  254.         if ((rows*puzzle.ph) < (dest->Height-2))
  255.         {   /* enough room for a nice bottom border */
  256.             for (c=0;c<columns;c++)
  257.                 DrawRectBorder(c*puzzle.pw,       rows*puzzle.ph,
  258.                                (c+1)*puzzle.pw-1, dest->Height-1);
  259.             /* test if the bottom right edge can be drawn with a border */
  260.             if ((columns*puzzle.pw) < (dest->Width-2))
  261.             {   /* enough room for a nice bottom right border */
  262.                 DrawRectBorder(columns*puzzle.pw, rows*puzzle.ph,
  263.                                dest->Width-1,     dest->Height-1);
  264.             }
  265.         }
  266.         else if ((rows*puzzle.ph) < dest->Height)
  267.         {   /* not enough room for a nice bottom border but a background strip */
  268.             SetAPen(puzzle.destrp,ColBack);
  269.             RectFill(puzzle.destrp,
  270.                      0,             rows*puzzle.ph,
  271.                      dest->Width-1, dest->Height-1);
  272.         }
  273.     }
  274.  
  275.     /* At last clear the hole piece */
  276.     SetAPen(puzzle.destrp,ColHole);
  277.     RectFill(puzzle.destrp, puzzle.hx*puzzle.pw, puzzle.hy*puzzle.ph,
  278.                             (puzzle.hx+1)*puzzle.pw-1, (puzzle.hy+1)*puzzle.ph-1);
  279. }
  280. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  281.  * doStep        "Do one step of movement"
  282.  *
  283.  * Parameters:  none
  284.  *
  285.  * Result:      none
  286.  *
  287.  * Function:    Redraws the whole puzzle with one step of movement done
  288.  *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  289. void doStep (void)
  290. {
  291.     long  r,c;      /* row, column counter */
  292.     long  px,py;    /* piece which is currently moving */
  293.     long  dx,dy;             /* piece's moving offset */
  294.     long  pxl,pxr,pyt,pyb;   /* dest coordinates */
  295.  
  296.     BOOL  onemovecompleted = FALSE;
  297.  
  298.     switch (puzzle.from)
  299.     {
  300.         case down:  dx = 0;
  301.                     dy = - puzzle.ph * puzzle.step / puzzle.steps;
  302.                     px = puzzle.hx;
  303.                     py = puzzle.hy+1;
  304.                     break;
  305.         case up:    dx = 0;
  306.                     dy = puzzle.ph * puzzle.step / puzzle.steps;
  307.                     px = puzzle.hx;
  308.                     py = puzzle.hy-1;
  309.                     break;
  310.         case right: dx = - puzzle.pw * puzzle.step / puzzle.steps;
  311.                     dy = 0;
  312.                     px = puzzle.hx+1;
  313.                     py = puzzle.hy;
  314.                     break;
  315.         case left:  dx = puzzle.pw * puzzle.step / puzzle.steps;
  316.                     dy = 0;
  317.                     px = puzzle.hx-1;
  318.                     py = puzzle.hy;
  319.                     break;
  320.     }
  321.  
  322.     for (r=0;r<puzzle.rows;r++)
  323.     {
  324.         for (c=0;c<puzzle.columns;c++)
  325.         {
  326.             if ((r == puzzle.hy) && (c == puzzle.hx))                                       /* HOLE */
  327.             {
  328.                 /* nothing to do, 'cause the hole is slowly filled by the moving piece */
  329.             }
  330.             else
  331.             {
  332.                 if ((r == py) && (c == px))                                                 /* MOVE */
  333.                 {
  334.                     /* update the moving piece */
  335.                     BltBitMap(puzzle.srcscr->RastPort.BitMap,
  336.                                (puzzle.pieces[r][c].srcx)*puzzle.pw,
  337.                                (puzzle.pieces[r][c].srcy)*puzzle.ph,
  338.                               puzzle.destrp->BitMap,
  339.                                pxl = c*puzzle.pw+dx,
  340.                                pyt = r*puzzle.ph+dy,
  341.                               puzzle.pw,
  342.                               puzzle.ph,
  343.                               0xc0,0xff,NULL);
  344.  
  345.                     if (puzzle.doborder)
  346.                     {
  347.                         pxr = pxl + puzzle.pw-1;
  348.                         pyb = pyt + puzzle.ph-1;
  349.                         DrawRectBorder(pxl,pyt,pxr,pyb);  /* draw the border of this piece */
  350.                     }
  351.                     /* fill the new hole (erase the old piece data there) */
  352.                     if (dx || dy)
  353.                     {
  354.                         long    xtl,ytl,xbr,ybr;    /* new hole's rectangular coordinates */
  355.                         switch (puzzle.from)
  356.                         {
  357.                             case left:  xtl = c * puzzle.pw;
  358.                                         xbr = c * puzzle.pw + dx - 1;
  359.                                         ytl = r * puzzle.ph;
  360.                                         ybr = r * puzzle.ph + puzzle.ph - 1;
  361.                                         break;
  362.                             case right: xtl = c * puzzle.pw + puzzle.pw + dx;
  363.                                         xbr = c * puzzle.pw + puzzle.pw - 1;
  364.                                         ytl = r * puzzle.ph;
  365.                                         ybr = r * puzzle.ph + puzzle.ph - 1;
  366.                                         break;
  367.                             case up:    ytl = r * puzzle.ph;
  368.                                         ybr = r * puzzle.ph + dy - 1;
  369.                                         xtl = c * puzzle.pw;
  370.                                         xbr = c * puzzle.pw + puzzle.pw - 1;
  371.                                         break;
  372.                             case down:  ytl = r * puzzle.ph + puzzle.ph + dy;
  373.                                         ybr = r * puzzle.ph + puzzle.ph - 1;
  374.                                         xtl = c * puzzle.pw;
  375.                                         xbr = c * puzzle.pw + puzzle.pw - 1;
  376.                                         break;
  377.                         }
  378.                         SetAPen(puzzle.destrp,ColHole);
  379.                         RectFill(puzzle.destrp,xtl,ytl,xbr,ybr);
  380.                     }
  381.  
  382.                     if (++puzzle.step > puzzle.steps)   onemovecompleted = TRUE;
  383.                 }
  384.                 else                                                                        /* STILL */
  385.                 {
  386.                     if (puzzle.doborder)
  387.                     {
  388.                         /* do a simple actualizing (first without border) */
  389.                         BltBitMap(puzzle.srcscr->RastPort.BitMap,           /* source bitmap */
  390.                                   (puzzle.pieces[r][c].srcx)*puzzle.pw+1,
  391.                                   (puzzle.pieces[r][c].srcy)*puzzle.ph+1,   /* src coord */
  392.                                   puzzle.destrp->BitMap,                    /* dest bitmap */
  393.                                   (pxl=c*puzzle.pw)+1,
  394.                                   (pyt=r*puzzle.ph)+1,                      /* dest coord */
  395.                                   puzzle.pw-2,
  396.                                   puzzle.ph-2,                              /* piece size without border */
  397.                                   0xc0,0xff,NULL);                          /* minterm, planemask,tempbuf */
  398.                         /* now add the border */
  399.                         pxr = pxl + puzzle.pw -1;
  400.                         pyb = pyt + puzzle.ph -1;
  401.                         DrawRectBorder(pxl,pyt,pxr,pyb);
  402.                     }
  403.                     else
  404.                     {
  405.                         /* do a simple actualizing */
  406.                         BltBitMap(puzzle.srcscr->RastPort.BitMap,           /* source bitmap */
  407.                                   (puzzle.pieces[r][c].srcx)*puzzle.pw,
  408.                                   (puzzle.pieces[r][c].srcy)*puzzle.ph,     /* src coord */
  409.                                   puzzle.destrp->BitMap,                    /* dest bitmap */
  410.                                   c*puzzle.pw,
  411.                                   r*puzzle.ph,                              /* dest coord */
  412.                                   puzzle.pw,
  413.                                   puzzle.ph,                                /* piece size */
  414.                                   0xc0,0xff,NULL);                          /* minterm, planemask,tempbuf */
  415.                     }
  416.                 }
  417.             }
  418.         }
  419.     }
  420.     if (onemovecompleted)
  421.     {   /* swap hole and last moving piece */
  422.         puzzle.pieces[puzzle.hy][puzzle.hx].srcx =  puzzle.pieces[py][px].srcx;
  423.         puzzle.pieces[puzzle.hy][puzzle.hx].srcy =  puzzle.pieces[py][px].srcy;
  424.         switch (puzzle.from)
  425.         {
  426.             case down:  puzzle.hy++; break;
  427.             case up:    puzzle.hy--; break;
  428.             case left:  puzzle.hx--; break;
  429.             case right: puzzle.hx++; break;
  430.         }
  431.         /* select new direction */
  432.         getNewDir();
  433.         puzzle.step = 0;
  434.     }
  435. }
  436. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  437.  * initSimplePuzzle        "Initialize only the parts of the puzzle needed for simple shuffling"
  438.  *
  439.  * Parameters:
  440.  *
  441.  * Result:      none
  442.  *
  443.  * Function:    Initializes all fields
  444.  *
  445.  * Note:    Ever call this function with valid screen pointers !!!
  446.  *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  447. void initSimplePuzzle (struct Screen *dest, long columns, long rows, long steps)
  448. {
  449.     long    r,c;
  450.  
  451.     puzzle.columns = columns;
  452.     puzzle.rows = rows;
  453.     puzzle.steps = steps;
  454.     puzzle.pw = dest->Width / columns;
  455.     puzzle.ph = dest->Height / rows;
  456.  
  457.     puzzle.srcscr = NULL;
  458.     puzzle.destrp = &(dest->RastPort);
  459.  
  460.     puzzle.hx = RndBT(0,columns-1);
  461.     puzzle.hy = RndBT(0,rows-1);
  462.     puzzle.step = 0;
  463.     puzzle.from = (direction)RndBT(0,3);
  464.     getNewDir();  /* to do bordercorrections */
  465.  
  466.     if (puzzle.doborder)
  467.     {
  468.         /* Draw the pieces' border */
  469.         for (r=0;r<rows;r++)
  470.             for (c=0;c<columns;c++)
  471.                 DrawRectBorder( c*puzzle.pw, r*puzzle.ph, (c+1)*puzzle.pw-1, (r+1)*puzzle.ph-1 );
  472.         /* Now draw a nice right border puzzle (which isn't shuffled, because it's too small) */
  473.         if ((columns*puzzle.pw) < (dest->Width-2))
  474.         {   /* enough room for a nice right border */
  475.             for (r=0;r<rows;r++)
  476.                 DrawRectBorder(columns*puzzle.pw, r*puzzle.ph,
  477.                                dest->Width-1,     (r+1)*puzzle.ph-1);
  478.         }
  479.         else if ((columns*puzzle.pw) < dest->Width)
  480.         {   /* not enough room for a nice right border but a background strip */
  481.             SetAPen(puzzle.destrp,ColBack);
  482.             RectFill(puzzle.destrp,
  483.                      columns*puzzle.pw, 0,
  484.                      dest->Width-1,     dest->Height-1);
  485.         }
  486.         /* Now draw a nice bottom border puzzle (which isn't shuffled, because it's too small) */
  487.         if ((rows*puzzle.ph) < (dest->Height-2))
  488.         {   /* enough room for a nice bottom border */
  489.             for (c=0;c<columns;c++)
  490.                 DrawRectBorder(c*puzzle.pw,       rows*puzzle.ph,
  491.                                (c+1)*puzzle.pw-1, dest->Height-1);
  492.             /* test if the bottom right edge can be drawn with a border */
  493.             if ((columns*puzzle.pw) < (dest->Width-2))
  494.             {   /* enough room for a nice bottom right border */
  495.                 DrawRectBorder(columns*puzzle.pw, rows*puzzle.ph,
  496.                                dest->Width-1,     dest->Height-1);
  497.             }
  498.         }
  499.         else if ((rows*puzzle.ph) < dest->Height)
  500.         {   /* not enough room for a nice bottom border but a background strip */
  501.             SetAPen(puzzle.destrp,ColBack);
  502.             RectFill(puzzle.destrp,
  503.                      0,             rows*puzzle.ph,
  504.                      dest->Width-1, dest->Height-1);
  505.         }
  506.     }
  507.  
  508.     /* At last clear the hole piece */
  509.     SetAPen(puzzle.destrp,ColHole);
  510.     RectFill(puzzle.destrp, puzzle.hx*puzzle.pw, puzzle.hy*puzzle.ph,
  511.                             (puzzle.hx+1)*puzzle.pw-1, (puzzle.hy+1)*puzzle.ph-1);
  512. }
  513. /*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
  514.  * doSimpleStep   "Do one step of movement just shuffling no updating"
  515.  *
  516.  * Parameters:  none
  517.  *
  518.  * Result:      none
  519.  *
  520.  * Function:    Redraws the whole puzzle with one step of movement done
  521.  *°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
  522. void doSimpleStep (void)
  523. {
  524.     long  px,py;    /* piece which is currently moving */
  525.     long  dx,dy;             /* piece's moving offset */
  526.     long  olddx,olddy;       /* piece's last moving offset */
  527.     long  pxl,pxr,pyt,pyb;   /* dest coordinates */
  528.  
  529.     switch (puzzle.from)
  530.     {
  531.         case down:  dx = 0;
  532.                     dy = - puzzle.ph * puzzle.step / puzzle.steps;
  533.                     olddx = 0;
  534.                     if (puzzle.step) olddy = - puzzle.ph * (puzzle.step-1) / puzzle.steps;
  535.                     else             olddy = 0;
  536.                     px = puzzle.hx;
  537.                     py = puzzle.hy+1;
  538.                     break;
  539.         case up:    dx = 0;
  540.                     dy = puzzle.ph * puzzle.step / puzzle.steps;
  541.                     olddx = 0;
  542.                     if (puzzle.step) olddy = puzzle.ph * (puzzle.step-1) / puzzle.steps;
  543.                     else             olddy = 0;
  544.                     px = puzzle.hx;
  545.                     py = puzzle.hy-1;
  546.                     break;
  547.         case right: dx = - puzzle.pw * puzzle.step / puzzle.steps;
  548.                     dy = 0;
  549.                     if (puzzle.step) olddx = - puzzle.pw * (puzzle.step-1) / puzzle.steps;
  550.                     else             olddx = 0;
  551.                     olddy = 0;
  552.                     px = puzzle.hx+1;
  553.                     py = puzzle.hy;
  554.                     break;
  555.         case left:  dx = puzzle.pw * puzzle.step / puzzle.steps;
  556.                     dy = 0;
  557.                     if (puzzle.step) olddx = puzzle.pw * (puzzle.step-1) / puzzle.steps;
  558.                     else             olddx = 0;
  559.                     olddy = 0;
  560.                     px = puzzle.hx-1;
  561.                     py = puzzle.hy;
  562.                     break;
  563.     }
  564.     /* update the moving piece */
  565.     BltBitMap(puzzle.destrp->BitMap, px*puzzle.pw+olddx, py*puzzle.ph+olddy,
  566.               puzzle.destrp->BitMap, pxl = px*puzzle.pw+dx, pyt = py*puzzle.ph+dy,
  567.               puzzle.pw, puzzle.ph,
  568.               0xc0,0xff,NULL);
  569.  
  570.     if (puzzle.doborder)
  571.     {
  572.         pxr = pxl + puzzle.pw-1;
  573.         pyb = pyt + puzzle.ph-1;
  574.         DrawRectBorder(pxl,pyt,pxr,pyb);  /* draw the border of this piece */
  575.     }
  576.  
  577.     /* fill the new hole (erase the old piece data there) */
  578.     if (dx || dy)
  579.     {
  580.         long    xtl,ytl,xbr,ybr;    /* new hole's rectangular coordinates */
  581.         switch (puzzle.from)
  582.         {
  583.             case left:  xtl = px * puzzle.pw;
  584.                         xbr = px * puzzle.pw + dx - 1;
  585.                         ytl = py * puzzle.ph;
  586.                         ybr = py * puzzle.ph + puzzle.ph - 1;
  587.                         break;
  588.             case right: xtl = px * puzzle.pw + puzzle.pw + dx;
  589.                         xbr = px * puzzle.pw + puzzle.pw - 1;
  590.                         ytl = py * puzzle.ph;
  591.                         ybr = py * puzzle.ph + puzzle.ph - 1;
  592.                         break;
  593.             case up:    ytl = py * puzzle.ph;
  594.                         ybr = py * puzzle.ph + dy - 1;
  595.                         xtl = px * puzzle.pw;
  596.                         xbr = px * puzzle.pw + puzzle.pw - 1;
  597.                         break;
  598.             case down:  ytl = py * puzzle.ph + puzzle.ph + dy;
  599.                         ybr = py * puzzle.ph + puzzle.ph - 1;
  600.                         xtl = px * puzzle.pw;
  601.                         xbr = px * puzzle.pw + puzzle.pw - 1;
  602.                         break;
  603.         }
  604.         SetAPen(puzzle.destrp,ColHole);
  605.         RectFill(puzzle.destrp,xtl,ytl,xbr,ybr);
  606.     }
  607.  
  608.     if (++puzzle.step > puzzle.steps)
  609.     {   /* move hole */
  610.         switch (puzzle.from)
  611.         {
  612.             case down:  puzzle.hy++; break;
  613.             case up:    puzzle.hy--; break;
  614.             case left:  puzzle.hx--; break;
  615.             case right: puzzle.hx++; break;
  616.         }
  617.         /* select new direction */
  618.         getNewDir();
  619.         puzzle.step = 0;
  620.     }
  621. }
  622. /************************************************************************************************/
  623. /************************************************************************************************/
  624. /************************************************************************************************/
  625.  
  626. LONG Blank( PrefObject *Prefs )
  627. {
  628.     long RetVal, ToFrontCount = 0;
  629.  
  630.     struct Screen *srcscr,*destscr;
  631.     struct Window *win;
  632.  
  633.     long Rows,Columns,Steps,StepDelay;
  634.  
  635.     long i,delay;
  636.  
  637.     Columns   = Prefs[PREFS_HORIZ].po_Level;
  638.     Rows      = Prefs[PREFS_VERT].po_Level;
  639.     Steps     = Prefs[PREFS_DIVIS].po_Level;
  640.     StepDelay = Prefs[PREFS_DELAY].po_Level;
  641.  
  642.     srand48(time(NULL));    /* Set seek value for Unix's lrand48() function */
  643.                             /* lrand48() provides a number from 0..2**31    */
  644.     
  645.     if (OpenLibs())
  646.     {
  647.         if (Prefs[PREFS_UPDATE].po_Active == PREFS_UPDATE_YES)
  648.         {
  649.             /* get source screen pointer */
  650.             if (Prefs[PREFS_SCREEN].po_Active==PREFS_SCREEN_PUBLIC)
  651.             {
  652.                 srcscr = LockPubScreen(0L);
  653.                 UnlockPubScreen(0L,srcscr);
  654.             }
  655.             else
  656.             if (Prefs[PREFS_SCREEN].po_Active==PREFS_SCREEN_FRONT)
  657.             {
  658.                 ULONG lock = LockIBase(0);
  659.                 srcscr = IntuitionBase->FirstScreen;
  660.                 UnlockIBase(lock);
  661.             }
  662.             else srcscr=NULL;
  663.         }
  664.         else srcscr=NULL;
  665.         if(destscr=cloneTopScreen(FALSE,Prefs[PREFS_SCREEN].po_Active))
  666.         {
  667.             if (Prefs[PREFS_HOLE].po_Active == PREFS_HOLE_BACKGROUND)
  668.                  ColHole = ColBack;
  669.             else ColHole = RndBT(0,(1L<<destscr->RastPort.BitMap->Depth)-1);    /* choose a colour randomly */
  670.             if ((destscr->Width/Columns) < PIECE_MIN_WIDTH) Columns = destscr->Width/PIECE_MIN_WIDTH;
  671.             if ((destscr->Height/Rows) < PIECE_MIN_HEIGHT) Rows = destscr->Height/PIECE_MIN_HEIGHT;
  672.             if ((Columns>=2) && (Rows>=2))
  673.             {
  674.                 /* adjust steps if necessary */
  675.                 if ((destscr->Width/Columns/2) <= Steps) Steps = destscr->Width/Columns / 2;
  676.                 if ((destscr->Height/Rows/2) <= Steps) Steps = destscr->Height/Rows / 2;
  677.  
  678.                 if (srcscr || (Prefs[PREFS_UPDATE].po_Active==PREFS_UPDATE_NO))
  679.                 {
  680.                     if(Prefs[PREFS_FADEPCT].po_Level)
  681.                     {
  682.                         ULONG *ColorTable, PctCount, BPG;
  683.  
  684.                         ColorTable = GetColorTable(destscr);
  685.                         BPG = AvgBitsPerGun(getTopScreenMode());
  686.                         PctCount = (1L<<BPG) * Prefs[PREFS_FADEPCT].po_Level/100;
  687.                         for(i=0;i<PctCount;i++) FadeAndLoadTable(destscr,BPG,ColorTable,0);
  688.                     }
  689.                     puzzle.doborder = (Prefs[PREFS_BORDER].po_Active==PREFS_BORDER_YES)? TRUE:FALSE;
  690.                     if (Prefs[PREFS_UPDATE].po_Active == PREFS_UPDATE_YES)
  691.                          initPuzzle(srcscr,destscr,Columns,Rows,Steps); /* fetch gfx data from src scr */
  692.                     else initSimplePuzzle(destscr,Columns,Rows,Steps); /* simple shuffling */
  693.                     win = BlankMousePointer(destscr);
  694.                     
  695.                     delay = StepDelay;
  696.  
  697.                     while((RetVal=ContinueBlanking())==OK)
  698.                     {
  699.                         if(!(++ToFrontCount%64))    ScreenToFront(destscr);
  700.                         
  701.                         if (--delay)    Delay(1L);  /* delay for one tick */
  702.                         else
  703.                         {
  704.                             if (puzzle.step==0)
  705.                                 if (Prefs[PREFS_HOLE].po_Active == PREFS_HOLE_RANDOM)
  706.                                     ColHole = RndBT(0,(1L<<destscr->RastPort.BitMap->Depth)-1);
  707.                             delay = StepDelay;
  708.                             WaitTOF();
  709.                             if (Prefs[PREFS_UPDATE].po_Active == PREFS_UPDATE_YES)  doStep();
  710.                             else                                                    doSimpleStep();
  711.                         }
  712.  
  713.                     } /* end of while(RetVal==OK) */
  714.  
  715.                     UnblankMousePointer(win);
  716.                 }
  717.                 else RetVal = FAILED; /* couldn't get srcscr address */
  718.             }
  719.             else RetVal = FAILED;   /* too less columns or rows */
  720.  
  721.             CloseScreen(destscr);
  722.         }
  723.         else RetVal = FAILED;
  724.     }
  725.     else RetVal = FAILED;
  726.     CloseLibs();
  727.     return RetVal;
  728. }
  729.